﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using DotNetSpeech;

namespace KWBridge
{
    /// <summary>
    /// 语音报警结构
    /// </summary>
    public class SpeechMsg : IComparable
    {
        /// <summary>
        /// 传感器点号

        /// </summary>
        public string sId;

        /// <summary>
        /// 传感器类型

        /// </summary>
        public string sType;

        /// <summary>
        /// 报警信息
        /// </summary>
        public string sMsg;

        /// <summary>
        /// 报警优先级

        /// </summary>
        public SpeechPrioritys Priority;

        public SpeechMsg( )
        {
        }

        public SpeechMsg( string sId , string sType , string sMsg )
        {
            this.sId = sId;
            this.sType = sType;
            this.sMsg = sMsg;
            switch ( sType )
            {
                case "甲烷":
                    this.Priority = SpeechPrioritys.甲烷;
                    break;

                case "风机":
                    this.Priority = SpeechPrioritys.风机;
                    break;

                case "局扇":
                    this.Priority = SpeechPrioritys.局扇;
                    break;

                case "主扇":
                    this.Priority = SpeechPrioritys.主扇;
                    break;

                case "一氧化碳":
                    this.Priority = SpeechPrioritys.一氧化碳;
                    break;

                case "网络中断":
                    this.Priority = SpeechPrioritys.网络中断;
                    break;

                case "文件不存在":
                    this.Priority = SpeechPrioritys.文件不存在;
                    break;

                case "文件不变化":
                    this.Priority = SpeechPrioritys.文件不变化;
                    break;
                default:
                    this.Priority = SpeechPrioritys.其它;
                    break;
            }
        }

        #region 实现比较接口的CompareTo方法

        public int CompareTo( object obj )
        {
            SpeechMsg item = ( SpeechMsg )obj;
            try
            {
                if ( this.Priority < item.Priority )
                {
                    return 1;
                }
                else if ( this.Priority == item.Priority )
                {
                    return 0;
                }
                else
                {
                    return -1;
                }
            }
            catch ( Exception ex )
            {
                throw new Exception( "比较异常" , ex.InnerException );
            }
        }

        #endregion 实现比较接口的CompareTo方法
    }

    /// <summary>
    /// 语音报警优先级

    /// </summary>
    public enum SpeechPrioritys { 网络中断 = 0 , 文件不存在 = 0 , 文件不变化 = 0 , 甲烷 = 1 , 主扇 = 2 , 风机 = 3 , 局扇 = 3 , 一氧化碳 = 4 , 其它 = 5 };

    public class SpeechEventArgs : EventArgs
    {
        public string sMsg { get; set; }

        public SpeechEventArgs( string msg )
        {
            sMsg = msg;
        }
    }

    public delegate void DisptchErrorMessage( object sendor , SpeechEventArgs e );

    public class Speech
    {
        private BackgroundWorker worker;

        //private bool bFinished;
        private bool bWorking;

        public Dictionary<string , SpeechMsg> dic_Speech;

        public List<SpeechMsg> list_SpeechMsg;

        private Thread speechThread;

        public bool IsRunning { get; set; }

        /// <summary>
        /// 是否暂停语音报警
        /// </summary>
        public bool IsPause { get; set; }

        public int Interval { get; set; }

        public DisptchErrorMessage disptchErrorMessage;

        public Speech( )
        {
            dic_Speech = new Dictionary<string , SpeechMsg>( );
            list_SpeechMsg = new List<SpeechMsg>( );

            //bFinished = false;
            bWorking = false;
            worker = new BackgroundWorker( );
            worker.DoWork += new DoWorkEventHandler( worker_DoWork );
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( worker_RunWorkerCompleted );

            IsRunning = true;

            IsPause = false;

            Interval = 15;
            speechThread = new Thread( new ThreadStart( SpeechMessages ) );
            speechThread.Start( );
        }

        /// <summary>
        /// 关闭语音报警
        /// </summary>
        public void Close( )
        {
            IsRunning = false;
            while ( bWorking )
            {
                Thread.Sleep( 100 );
            }
            speechThread.Join( );
        }

        /// <summary>
        /// 语音报警线程程序
        /// </summary>
        private void SpeechMessages( )
        {
            do
            {
                if ( !bWorking && !IsPause )
                {
                    if ( dic_Speech.Count > 0 )
                    {
                        try
                        {
                            if ( !worker.IsBusy )
                            {
                                worker.RunWorkerAsync( );
                            }
                        }
                        catch ( System.Exception err )
                        {
                            ShowException( err );
                        }
                    }
                }
                DateTime t = DateTime.Now;
                int eslape = 0;
                do
                {
                    Thread.Sleep( 100 );
                    eslape = ( int )DateTime.Now.Subtract( t ).TotalSeconds;
                } while ( IsRunning && eslape < Interval );
            } while ( IsRunning );
        }

        /// <summary>
        /// 加入一条需要语音报警的信息
        /// </summary>
        /// <param name="sId">传感器点号</param>
        /// <param name="sMsg">报警信息</param>
        /// <param name="sType">传感器类型</param>
        public void AddSpeech( string sId , string sType , string sMsg )
        {
            SpeechMsg item;
            if ( dic_Speech.ContainsKey( sId ) )
            {
                lock ( dic_Speech )
                {
                    item = dic_Speech[ sId ];

                    //改变信息
                    if ( item.sMsg != sMsg )
                    {
                        item.sMsg = sMsg;
                        dic_Speech[ sId ] = item;
                        int index = list_SpeechMsg.IndexOf( item );
                        if ( index >= 0 )
                        {
                            list_SpeechMsg[ index ] = item;
                        }
                    }
                }
            }
            else
            {
                item = new SpeechMsg( sId , sType , sMsg );
                lock ( dic_Speech )
                {
                    dic_Speech.Add( sId , item );
                    list_SpeechMsg.Add( item );
                    SortSpeech( item );
                }
            }
        }

        /// <summary>
        /// 排序
        /// </summary>
        public void SortSpeech( SpeechMsg item )
        {
            list_SpeechMsg.Sort( );

            // 改变当前报警的顺序

            switch ( item.Priority )
            {
                case SpeechPrioritys.网络中断:
                case SpeechPrioritys.甲烷:
                case SpeechPrioritys.主扇:
                    index = -1;
                    break;
            }
        }

        /// <summary>
        /// 删除不报警的信息
        /// </summary>
        /// <param name="sId"></param>
        public void DeleteSpeech( string sId )
        {
            lock ( dic_Speech )
            {
                if ( dic_Speech.ContainsKey( sId ) )
                {
                    SpeechMsg item = dic_Speech[ sId ];
                    dic_Speech.Remove( sId );
                    list_SpeechMsg.Remove( item );
                }
            }
        }

        private int index = -1;

        public SpeechMsg TakeSpeechMsg( )
        {
            SpeechMsg item;
            if ( list_SpeechMsg.Count == 0 )
            {
                if ( dic_Speech.Count == 0 )
                {
                    return null;
                }

                // 重新安排报警内容
                list_SpeechMsg = dic_Speech.Values.ToList( );
                list_SpeechMsg.Sort( );

                index = -1;
            }
            index++;

            //lock (list_SpeechMsg)
            {
                if ( index >= list_SpeechMsg.Count )
                {
                    index = 0;
                }
                item = list_SpeechMsg[ index ];

                // 报过的测点信息可以删除

                list_SpeechMsg.RemoveAt( index );
            }
            if ( IsPause ) return null;

            return item;
        }

        public string 加注中文标记( string 原字符串 )
        {
            return string.Format( "<spell>{0}</spell>" , Regex.Replace( 原字符串 , @"(.)" , @"<voice required=""Language=804"">$1</voice>" ) );
        }

        private void worker_DoWork( object sender , DoWorkEventArgs e )
        {
            try
            {
                if ( bWorking )
                {
                    return;
                }
                bWorking = true;

                SpeechMsg item = TakeSpeechMsg( );
                if ( item != null )
                {
                    SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
                    SpVoice Voice = new SpVoice( );
                    Voice.Rate = 0; // -1 SpVoice EndStream
                    Voice.Volume = 100;
                    Voice.Speak( item.sMsg , SpFlags );
                    Voice.WaitUntilDone( 30 * 1000 );//System.Threading.Timeout.Infinite);
                    bWorking = false;
                }
            }
            catch ( Exception ex )
            {
                ShowException( ex );
            }
        }

        private void worker_RunWorkerCompleted( object sender , RunWorkerCompletedEventArgs e )
        {
            //throw new NotImplementedException();
            bWorking = false;
        }

        /// <summary>
        /// 显示异常信息
        /// </summary>
        /// <param name="ex"></param>
        private void ShowException( Exception ex )
        {
            if ( disptchErrorMessage != null )
            {
                SpeechEventArgs args = new SpeechEventArgs( ex.Message );

                disptchErrorMessage( this , args );
            }

            //else
            //{
            //    //MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //    //LogWrapper.Logger.Error(s);
            //}
        }

        public void GenWavFile( string sMsg )
        {
            // sMsg = "2211工作面 瓦斯超限，当前值 1.56";
            try
            {
                SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
                SpVoice Voice = new SpVoice( );
                SaveFileDialog sfd = new SaveFileDialog( );
                sfd.Filter = "All files (*.*)|*.*|wav files (*.wav)|*.wav";
                sfd.Title = "Save to a wave file";
                sfd.FilterIndex = 2;
                sfd.RestoreDirectory = true;
                if ( sfd.ShowDialog( ) == DialogResult.OK )
                {
                    SpeechStreamFileMode SpFileMode = SpeechStreamFileMode.SSFMCreateForWrite;
                    SpFileStream SpFileStream = new SpFileStream( );
                    SpFileStream.Open( sfd.FileName , SpFileMode , false );
                    Voice.AudioOutputStream = SpFileStream;
                    Voice.Speak( sMsg , SpFlags );
                    Voice.WaitUntilDone( System.Threading.Timeout.Infinite );
                    SpFileStream.Close( );
                }
            }
            catch ( Exception ex )
            {
                ShowException( ex );
            }
        }
    }
}